package pl.uz.zgora.plan;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;

import org.xmlpull.v1.XmlPullParserException;

import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.location.Address;

public class PlanUzDataSource {
	private SQLiteDatabase database;
	private PlanDatabaseHandler dbHelper;
	private GrupaDataSource grupaDataSource;
	private SalaDataSource salaDataSource;
	private NauczycielDataSource nauczycielDataSource;
	private PrzedmiotDataSource przedmiotDataSource;
	private BudynekDataSource budynekDataSource; 
	private Context mContext;
	private Integer currentClassLeft = -1;
	
	public PlanUzDataSource(Context context)
	{
		dbHelper = new PlanDatabaseHandler(context);
		mContext = context;
	}
	
	public PlanUzDataSource(Context context, boolean removeDB)
	{
		dbHelper = new PlanDatabaseHandler(context, removeDB);
		mContext = context;
	}
	
	public void openForWrite() throws SQLException
	{
		dbHelper.close();
		database = dbHelper.getWritableDatabase();
	}
	
	public void openForRead() throws SQLException
	{
		dbHelper.close();
		database = dbHelper.getReadableDatabase();
	}
	
	public boolean writePlan(final Plan plan)
	{
		openForWrite();
		
		if(plan.getGroup().getNazwa() != null) {
			grupaDataSource = new GrupaDataSource(database);
			if(!grupaDataSource.addGrupa(plan.getGroup()))
				return false;
		}
		
		if(plan.getTeacher() != null) {
			final Nauczyciel nauczyciel = plan.getTeacher();
			nauczycielDataSource = new NauczycielDataSource(database);
			if(!nauczycielDataSource.addNauczyciel(nauczyciel)) {
				return false;
			}
		} else {
			nauczycielDataSource = new NauczycielDataSource(database);
			if(!nauczycielDataSource.addNauczycielList(plan.getNauczycieli())) {
				return false;
			}
		}
		
		przedmiotDataSource = new PrzedmiotDataSource(database);
		if(!przedmiotDataSource.addPrzedmiotList(plan.getPrzedmioty())) {
			return false;
		}
		
		salaDataSource = new SalaDataSource(database);
		if(!salaDataSource.addSalaList(plan.getSale())) {
			return false;
		}
		
		close();
		
		return true;
	}
	
	public void writeDaysList(final ArrayList<Dzien> kalendarz, final String kalendarzId) {
		openForWrite();
		DzienDataSource dds = new DzienDataSource(database);
		dds.addDzienList(kalendarz, kalendarzId);
		close();
	}
	 
	public ArrayList<Dzien> getCalendar(String kalendarzId) throws ParseException {
		openForRead();
		DzienDataSource dds = new DzienDataSource(database);
		ArrayList<Dzien> kalendarz = dds.getDniForKaledarz(kalendarzId);
		close();
		return kalendarz;
	}
	
	public ArrayList<Dzien> getCalendar(String kalendarzId, String calType) throws ParseException {
		openForRead();
		DzienDataSource dds = new DzienDataSource(database);
		ArrayList<Dzien> kalendarzTmp = dds.getDniForKaledarz(kalendarzId);
		ArrayList<Dzien> kalendarz = new ArrayList<Dzien>();
		if(calType.equals("P")) {
			for(Dzien d: kalendarzTmp) {
				if(Integer.valueOf(d.getTydzien().replace(" \r\n", "")) % 2 == 0) {
					kalendarz.add(d);
				}
			}
		} else if(calType.equals("N")) {
			for(Dzien d: kalendarzTmp) {
				if(Integer.valueOf(d.getTydzien().replace(" \r\n", "")) % 2 == 1) {
					kalendarz.add(d);
				}
			}
		}
		close();
		return kalendarz;
	}
	
	public void writeCalendarsInfoList(final ArrayList<KalendarzTyp> infos) {
		openForWrite();
		KalendarzTypDataSource ds = new KalendarzTypDataSource(database);
		ds.addKalendarzInfoList(infos);
		close();
	}
	
	public ArrayList<KalendarzTyp> getCalendarsTypeList() {
		openForRead();
		final KalendarzTypDataSource ds = new KalendarzTypDataSource(database);
		final ArrayList<KalendarzTyp> typyKalendarzy = ds.getKalendarzInfoList();
		close();
		return typyKalendarzy;
	}
	
	public Plan readPlan()
	{
		openForRead();
		
		ArrayList<Przedmiot> przedmioty = readPrzedmioty(null);
		ArrayList<Sala> sale = readSale(-1);
		ArrayList<Nauczyciel> nauczyciele = readNauczyciel(-1);
		
		ArrayList<String> idBudynkowList = new ArrayList<String>();

		for(Sala sala: sale)
		{
			if(!sala.getSymbolBudynku().equals("Uwagi")) { 
				if(!idBudynkowList.contains(sala.getSymbolBudynku())) { 
					idBudynkowList.add(sala.getSymbolBudynku()); 
				}
			}
			
		}
		
		String[] idBudynkow =  new String[idBudynkowList.size()];
		idBudynkowList.toArray(idBudynkow);
		
		Grupa grupa = readGrupa();
		
		ArrayList<Budynek> budynki = readBudynki(idBudynkow);
		
		Plan plan = new Plan(grupa, przedmioty, nauczyciele, sale, budynki);
		
		close();
		return plan;
	}
	
	public ArrayList<Przedmiot> readPrzedmioty(String dzien) throws SQLException {
		openForRead();
		
		ArrayList<Przedmiot> przedmioty = null;
		przedmiotDataSource = new PrzedmiotDataSource(database);
		
		if(dzien == null)
			przedmioty = przedmiotDataSource.getPrzedmioty();
		else
			przedmioty = przedmiotDataSource.getPrzedmioty(dzien);
		
		close();
		return przedmioty;
	}
	
	public ArrayList<Przedmiot> readPrzedmioty(String dzien, boolean weekView) throws SQLException, ParseException {
		openForRead();
		
		ArrayList<Przedmiot> przedmioty = null;
		przedmiotDataSource = new PrzedmiotDataSource(database);
		
		if(dzien == null)
			przedmioty = przedmiotDataSource.getPrzedmioty();
		else
			przedmioty = przedmiotDataSource.getPrzedmioty(dzien);
		
		close();
		if(weekView) {
			return przedmioty;
		} else { //TODO:  Widok dnia
			final PrefrencesManager pm = PrefrencesManager.getInstance(mContext);
			final String podgrupa = pm.getStringFromPreferences("podgrupa");
			ArrayList<Przedmiot> przedmiotyToReturn = new ArrayList<Przedmiot>();
			Calendar cal = Calendar.getInstance();
			ArrayList<KalendarzTyp> calendarTypes = getCalendarsTypeList();
			final SimpleDateFormat dateParser = new SimpleDateFormat("dd-MM-yyyy");
			for(Przedmiot p: przedmioty) {
				String notes = p.getUwagi();

				String[] calNameArray = notes.split("//");
				String calName = calNameArray[0];

				int todayDayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
				int todayMonth = cal.get(Calendar.MONTH);
				
				boolean foundCalendar = false;
				
				for(KalendarzTyp kt: calendarTypes) {
					if(notes.matches(kt.getNazwa() + ".*")) {
						foundCalendar = true;
						ArrayList<Dzien> kalendarz = null;

						String calType = calName.substring(calName.length() - 1);
						if(calType.equals("P") || calType.equals("N")) {
							kalendarz = getCalendar(kt.getLink(), calType);
						} else {
							kalendarz = getCalendar(kt.getLink());
						}

						for(Dzien d: kalendarz) {
							Date kalendarzDate = dateParser.parse(d.getData());
							int classDayOfMonth = kalendarzDate.getDate();
							int classMonth = kalendarzDate.getMonth();
							if(classMonth == todayMonth && classDayOfMonth == todayDayOfMonth) {
								if (HelperMethodsManager.isEmpty(p
										.getPodgrupa())
										|| p.getPodgrupa().equals(podgrupa)) {
									przedmiotyToReturn.add(p);
								}
								break;
							}
						}
						break;
					}
				} // for(KalendarzTyp kt: calendarTypes) end
				if(foundCalendar == false) {
					String[] days = p.getUwagi().split(";");
					for(int i = 0; i < days.length; i++) {
						if(days[i].matches("[0-9]{2}-[0-9]{2}-[0-9]{4}")) {
							Date date = dateParser.parse(days[i]);
							if(date.getDate() == todayDayOfMonth && date.getMonth() == todayMonth) { 
								przedmiotyToReturn.add(p); break; 
							}
						}
					}
				}

			}
			return przedmiotyToReturn;
		}
	}
	
	
	
	public Przedmiot getNextTodayClass() throws ParseException, SQLException, IOException, XmlPullParserException {
		final String dayOfWeek = HelperMethodsManager.getTodayDayName();

		Przedmiot nextTodayClass = null;

		final ArrayList<Przedmiot> przedmioty = readPrzedmioty(dayOfWeek, false);
		// Zajęcia odbywają się dzisiaj
		if(przedmioty != null && przedmioty.size() > 0) {
			final Iterator<Przedmiot> iterator = przedmioty.iterator();
			final Calendar calendar = Calendar.getInstance();
			final Integer currentHour = calendar.get(Calendar.HOUR_OF_DAY);
			final Integer currentMinute = calendar.get(Calendar.MINUTE);
			final SimpleDateFormat hourParser = new SimpleDateFormat("HH:mm");
			// Godzina rozpoczęcia zajęć
			Date classStartHour = null;
			final int currentMonth = calendar.get(Calendar.MONTH);
			final int currentDay = calendar.get(Calendar.DAY_OF_MONTH);
			final SimpleDateFormat dateParser = new SimpleDateFormat("dd-MM-yyyy");
			while(iterator.hasNext()) {
				final Przedmiot przedmiot = iterator.next();
				
				classStartHour = hourParser.parse(przedmiot.getGodzinaRozpoczecia());
				// Zajęcia już trwają
				if(currentHour > classStartHour.getHours()) {
					continue; // Zajęcia już się rozpoczęły
				} else if(currentHour == classStartHour.getHours() && currentMinute > classStartHour.getMinutes()) {
					continue;
				} else { // Zajęcia jeszcze się nie rozpoczęły
					ArrayList<KalendarzTyp> calendarTypes = getCalendarsTypeList();
					
					String[] calNameArray = przedmiot.getUwagi().split("//");
					String calName = calNameArray[0];
					String[] days = przedmiot.getUwagi().split(";");
					if(!days[0].matches("[0-9]{2}-[0-9]{2}-[0-9]{4}")) {
						for(KalendarzTyp kt: calendarTypes) {
							int i = 0;
							if(przedmiot.getUwagi().matches(kt.getNazwa() + ".*")) {
								//TODO: Obsługa kalendarzy

								ArrayList<Dzien> kalendarz = null;

								String calType = calName.substring(calName.length() - 1);
								if(calType.equals("P") || calType.equals("N")) {
									kalendarz = getCalendar(kt.getLink(), calType);
								} else {
									kalendarz = getCalendar(kt.getLink());
								}

								for(i = 0; i < kalendarz.size(); i++) {
									Date kalendarzDate = dateParser.parse(kalendarz.get(i).getData());
									if(kalendarzDate.getMonth() >= currentMonth) {
										if(kalendarzDate.getDate() >= currentDay) {
											nextTodayClass = przedmiot;
											break;
										}
									}
								}
								if(i < kalendarz.size()) { break; }
							}
						}
					}
					if(nextTodayClass != null) { break; }
					
					
					for(int i = 0; i < days.length; i++) {
						if(days[i].matches("[0-9]{2}-[0-9]{2}-[0-9]{4}")) {
							Date date = dateParser.parse(days[i]);
							if(date.getDate() == currentDay && date.getMonth() == currentMonth) { 
								nextTodayClass = przedmiot; break; 
							}
						}
					}
					//
					if(nextTodayClass != null) { break; }
				}
			}
		}

		return nextTodayClass;
	}
	
	public Przedmiot getNextClassFromOtherDay() throws ParseException, IOException, XmlPullParserException {
		String dzienOut = null;
		String dayOfWeek = HelperMethodsManager.getTodayDayName();
		final String[] dayNames = HelperMethodsManager.getFixedDayNames();
		final String podgrupa = PrefrencesManager.getInstance(mContext).getStringFromPreferences("podgrupa");
		Calendar cal = Calendar.getInstance();
		boolean passWeek = false;
		Integer todayDayNumber = 0;
		
		for(int i = 0; i < dayNames.length; i++) {
			if(dayNames[i].equals(dayOfWeek)) {
				todayDayNumber = i;
				break;
			}
		}
		
		// Numer następnego dnia
		Integer dayNumber = todayDayNumber + 1;
		Integer daysToAdd = 1;
		
		ArrayList<KalendarzTyp> calendarTypes = getCalendarsTypeList();
		final SimpleDateFormat dateParser = new SimpleDateFormat("dd-MM-yyyy");
		final Calendar classCalendar = Calendar.getInstance();
		dateParser.setCalendar(classCalendar);
		ArrayList<Przedmiot> przedmioty = new ArrayList<Przedmiot>();
		Przedmiot selectedPrzedmiot = null;
		while((dayNumber != todayDayNumber && przedmioty.size() == 0) || passWeek) {
			if(passWeek == true) { passWeek = false; }
			dayNumber = dayNumber % dayNames.length;
			
			dayOfWeek = dayNames[dayNumber];
			if(readPrzedmioty(null).isEmpty()) {
				return null;
			}
			przedmioty = readPrzedmioty(dayOfWeek, true);
			//
			//
			if(przedmioty.size() > 0) {
				cal.add(Calendar.DAY_OF_YEAR, daysToAdd);
				daysToAdd += 1;
			} else {
				daysToAdd += 1;
			}
			for(int i = 0; i < przedmioty.size(); i++) {
				String notes = przedmioty.get(i).getUwagi();
				
				String[] calNameArray = notes.split("//");
				
				if(notes.matches(".*Dzienne.*")) {
					calNameArray = notes.split(" -");
				}
				String calName = calNameArray[0];
				
				String[] days = notes.split(";");
				if(!days[0].trim().matches("[0-9]{2}-[0-9]{2}-[0-9]{4}")) {
					for(KalendarzTyp kt: calendarTypes) {
						if(notes.matches(kt.getNazwa() + ".*")) {

							ArrayList<Dzien> kalendarz = null;

							String calType = calName.substring(calName.length() - 1);
							if(calType.equals("P") || calType.equals("N")) {
								kalendarz = getCalendar(kt.getLink(), calType);
							} else {
								kalendarz = getCalendar(kt.getLink());
							}

							Collections.sort(kalendarz, Dzien.getComparator());

							// TODO: Obsługa kalendarza

							if(kalendarz.isEmpty()) {
								return null;
							}
							dateParser.parse(kalendarz.get(0).getData());
							dzienOut = kalendarz.get(0).getData();
							int todayDayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
							int todayMonth = cal.get(Calendar.MONTH);
							int todayWeek = cal.get(Calendar.WEEK_OF_MONTH);
							int classWeek = classCalendar.get(Calendar.WEEK_OF_MONTH);
							int classDayOfMonth = classCalendar.get(Calendar.DAY_OF_MONTH);
							int classMonth = classCalendar.get(Calendar.MONTH);

							int counter = 1;
							// TODO: przetestować
							// Dopóki dzień rozpoczęcia zajęć jest mniejszy niż dzień dzisiejszy
							while(classDayOfMonth < todayDayOfMonth && counter < kalendarz.size()) {
								dateParser.parse(kalendarz.get(counter).getData());
								dzienOut = kalendarz.get(counter).getData();
								classWeek = classCalendar.get(Calendar.WEEK_OF_MONTH);
								classDayOfMonth = classCalendar.get(Calendar.DAY_OF_MONTH);
								classMonth = classCalendar.get(Calendar.MONTH);
								counter++;
								if(classMonth > todayMonth) {
									break;
								}
							}
							// Jeżeli miesiąc jest większy lub równy
							if(classMonth >= todayMonth) {
								// Jeżeli dzień jest większy lub równy
								//if(classDayOfMonth >= todayDayOfMonth) {
									selectedPrzedmiot =  przedmioty.get(i);
									if(HelperMethodsManager.isEmpty(selectedPrzedmiot.getPodgrupa()) || selectedPrzedmiot.getPodgrupa().equals(podgrupa)) {
										selectedPrzedmiot.setData(dzienOut);
										if(classWeek == todayWeek || passWeek) {
											return selectedPrzedmiot;
										}
									}
									break;
								//}
							}
						}
					}
				} // if(!days[0].trim().matches("[0-9]{2}-[0-9]{2}-[0-9]{4}"))
				
				
				for(int x = 0; x < days.length; x++) {
					if(days[x].trim().matches("[0-9]{2}-[0-9]{2}-[0-9]{4}")) {
						Date date = dateParser.parse(days[x]);
						dzienOut = days[x];
						if(date.getDate() == cal.get(Calendar.DAY_OF_MONTH) && date.getMonth() == cal.get(Calendar.MONTH)) { 
							selectedPrzedmiot = przedmioty.get(i);
							if(HelperMethodsManager.isEmpty(selectedPrzedmiot.getPodgrupa()) || selectedPrzedmiot.getPodgrupa().equals(podgrupa)) {
								selectedPrzedmiot.setData(dzienOut);
								return selectedPrzedmiot;
							}
						}
					}
				}
			} // if(przedmioty.size > 0)
			passWeek = true;
			przedmioty.clear();
			cal = Calendar.getInstance();
			dayNumber += 1;
			
		}

		return null;
		
	}
	
	public Integer getCurrentClassLeft() {
		return currentClassLeft;
	}
	
	public Przedmiot getCurrentClass() throws ParseException {
		final String dayOfWeek = HelperMethodsManager.getTodayDayName();
		final String podgrupa = PrefrencesManager.getInstance(mContext).getStringFromPreferences("podgrupa");
		Przedmiot currentClass = null;

		final ArrayList<Przedmiot> przedmioty = readPrzedmioty(dayOfWeek, false);
		if(przedmioty != null) {
			final Iterator<Przedmiot> iterator = przedmioty.iterator();
			Calendar calendar = Calendar.getInstance();
			final Integer currentHour = calendar.get(Calendar.HOUR_OF_DAY);
			final Integer currentMinute = calendar.get(Calendar.MINUTE);
			final SimpleDateFormat parser = new SimpleDateFormat("HH:mm");
			Date classStartHour = null;
			Date classEndHour = null;

			while(iterator.hasNext()) {
				final Przedmiot przedmiot = iterator.next();
				if(HelperMethodsManager.isEmpty(przedmiot.getPodgrupa()) || przedmiot.getPodgrupa().equals(podgrupa)) {
					classStartHour = parser.parse(przedmiot.getGodzinaRozpoczecia());
					classEndHour = parser.parse(przedmiot.getGodzinaZakonczenia());

					if((currentHour >= classStartHour.getHours()) && (currentHour <= classEndHour.getHours())) {
						if(currentHour == classEndHour.getHours() && currentMinute < classEndHour.getMinutes() ) {
							currentClass = przedmiot;
							currentClassLeft = (classEndHour.getHours() - currentHour) * 60 + (classEndHour.getMinutes() - currentMinute);
							break;
						} else if(currentHour < classEndHour.getHours() && currentMinute > classStartHour.getMinutes()) {
							currentClass = przedmiot;
							currentClassLeft = (classEndHour.getHours() - currentHour) * 60 + (classEndHour.getMinutes() - currentMinute);
							break;
						} else if(currentHour < classEndHour.getHours() && currentHour > classStartHour.getHours() ) {
							currentClass = przedmiot;
							currentClassLeft = (classEndHour.getHours() - currentHour) * 60 + (classEndHour.getMinutes() - currentMinute);
							break;
						}
					}
				}
			}
		}
		
		return currentClass;
	}
	
	public ArrayList<Budynek> readBudynki(String[] idBudynkow)
	{
		openForRead();
		
		ArrayList<Budynek> budynki = null;
		budynekDataSource = new BudynekDataSource(database);
		
		if(idBudynkow != null && idBudynkow.length > 0) {
			budynki = budynekDataSource.getBudynki(idBudynkow);
		}
		
		close();
		return budynki;
	}
 	
	public ArrayList<Sala> readSale(Integer idSali) {
		openForRead();
		
		ArrayList<Sala> sale = null;
		salaDataSource = new SalaDataSource(database);
		
		if(idSali > 0)
		{
			sale = new ArrayList<Sala>(1);
			sale.add(salaDataSource.getSala(idSali));
		}
		else
			sale = salaDataSource.getSale();
		
		close();
		return sale;
	}
	
	public ArrayList<Nauczyciel> readNauczyciel(Integer idNauczyciela) {
		openForRead();
		
		ArrayList<Nauczyciel> nauczyciele = null;
		nauczycielDataSource = new NauczycielDataSource(database);
		
		if(idNauczyciela > 0) 
		{
			nauczyciele = new ArrayList<Nauczyciel>(1);
			nauczyciele.add(nauczycielDataSource.getNauczyciela(idNauczyciela));
		} 
		else 
			nauczyciele = nauczycielDataSource.getNauczecieli();
		
		close();
		
		return nauczyciele;
	}
	
	public Grupa readGrupa()
	{
		openForRead();
		
		grupaDataSource = new GrupaDataSource(database);
		Grupa grupa = grupaDataSource.getGrupa(); 
		
		close();
		
		return grupa; 
	}
	
	public void writeNauczycielePers(final ArrayList<Nauczyciel> nauczyciele) {
		
	}
	
	public void close()
	{
		dbHelper.close();
	}
}
